import { _decorator, Component, director, Node } from 'cc';
const { ccclass, property, executionOrder } = _decorator;

import UI from "../../../../Script/Manager/UI";
import { Minesweeper_GameData } from "../Data/Minesweeper_GameData";
import Minesweeper_GamePanel from "../UI/Minesweeper_GamePanel";
import Minesweeper_LosePanel from "../UI/Minesweeper_LosePanel";
import Minesweeper_WinPanel from "../UI/Minesweeper_WinPanel";
import Minesweeper_CardFunctions from "./Minesweeper_CardFunctions";
import Minesweeper_Grid from "./Minesweeper_Grid";

// /** GameManager */
// // 慢一点执行
@ccclass('MinesweeperGameManager')
@executionOrder(101)
export default class Minesweeper_GameManager extends Component {
        static Instance: Minesweeper_GameManager;
        @property(Node)
        Root_grid: Node | null = null;
        @property(Node)
        Root_block: Node | null = null;
        //    // 游戏状态
        private _isFirstClick: boolean = true;
        private _minesPlaced: boolean = false;
        //    /**
        //     * 重置/重新开始扫雷游戏
        //     */
        resetGame() {
                console.log("开始重置扫雷游戏...");

                try {
                        // 1. 清空Root_grid下所有子节点
                        if (this.Root_grid) {
                                this.Root_grid.removeAllChildren();
                                console.log("已清空Root_grid");
                        }

                        // 2. 清空Root_block下所有子节点（如果有）
                        if (this.Root_block) {
                                this.Root_block.removeAllChildren();
                                console.log("已清空Root_block");
                        }

                        // 3. 完全重置游戏数据
                        Minesweeper_GameData.InitData();
                        Minesweeper_GameData.ClearData();

                        // 4. 重置额外的游戏状态
                        Minesweeper_GameData.已翻格子数 = 0;
                        Minesweeper_GameData.状态 = "扫雷";
                        Minesweeper_GameData.IsMouseDown = false;
                        Minesweeper_GameData.isSlide = true;
                        Minesweeper_GameData.direction = null;
                        Minesweeper_GameData.gameState = null;

                        // 5. 清空网格数组
                        Minesweeper_GameData.arrGrids = [];
                        Minesweeper_GameData.arrBlocks = [];

                        // 6. 重置第一次点击状态
                        this._isFirstClick = true;
                        this._minesPlaced = false;

                        console.log("游戏数据已重置");

                        // 7. 重置UI状态（如果有GamePanel实例）
                        if (Minesweeper_GamePanel.Instance) {
                                Minesweeper_GamePanel.Instance.Refresh();
                                console.log("UI状态已刷新");
                        }

                        // 8. 重新初始化
                        this.Init();

                        console.log("扫雷游戏重置完成");

                } catch (error) {
                        console.error("重置游戏时发生错误:", error);
                        // 如果重置失败，尝试重新加载场景
                        this.fallbackReset();
                }
        }

        //    /**
        //     * 备用重置方法 - 如果正常重置失败，重新加载场景
        //     */
        private fallbackReset() {
                console.log("使用备用重置方法 - 重新加载场景");
                let currentSceneName = director.getScene().name;
                director.loadScene(currentSceneName);
        }
        //    // 移除重复Replay方法，只保留resetGame和Replay的别名
        //    // 兼容Replay命名
        Replay() {
                this.resetGame();
        }
        //    // 暴露到全局，方便调试和UI调用
        onLoad() {
                Minesweeper_GameManager.Instance = this;
                window["resetMinesweeper"] = this.resetGame.bind(this);
                window["testNoGuessMinesweeper"] = this.testNoGuessMinesweeper.bind(this);
                this.Init();
        }
        async Init() {
                // S2048_GameStorage.initData();
                Minesweeper_GameData.InitData();

                this.Init_map();

                Minesweeper_GamePanel.Instance.ShowOn();
        }
        async Init_map() {
                await this.Init_grid();
                // this.Init_block();
        }
        async Init_grid() {
                console.log("开始初始化网格...");

                // 预分配数组空间
                Minesweeper_GameData.arrGrids = Array(Minesweeper_GameData.row).fill(null).map(() =>
                        Array(Minesweeper_GameData.col).fill(null)
                );

                for (let r = 0; r < Minesweeper_GameData.row; r++) {
                        for (let c = 0; c < Minesweeper_GameData.col; c++) {
                                const id = 0;
                                let row = r + 0; // 使用0索引
                                let col = c + 0; // 使用0索引
                                const scrGrid: Minesweeper_Grid = await Minesweeper_CardFunctions.CreateGrid(col, row, id);
                                Minesweeper_GameData.arrGrids[r][c] = scrGrid;
                        }
                }

                console.log("网格初始化完成，等待第一次点击生成雷区...");
                // 不立即生成雷，等到第一次点击时再生成
        }
        初始化N个雷() {
                console.log("开始生成无猜扫雷雷区...");

                let maxAttempts = 100; // 最大尝试次数
                let attempt = 0;

                while (attempt < maxAttempts) {
                        attempt++;
                        console.log(`第${attempt}次尝试生成雷区`);

                        // 1. 清空所有雷
                        this.clearAllMines();

                        // 2. 随机放置雷
                        this.placeMinesRandomly();

                        // 3. 计算周围雷数量
                        this.计算每个格子周围雷数量();

                        // 4. 检查是否可解（无猜）
                        if (this.isSolvableWithoutGuessing()) {
                                console.log(`成功生成无猜雷区，尝试${attempt}次`);
                                return;
                        }

                        console.log(`第${attempt}次生成的雷区需要猜测，重新生成`);
                }

                // 如果多次尝试都失败，使用备用方案
                console.log("多次尝试失败，使用备用方案");
                this.generateFallbackMinesweeper();
        }

        //    // 清空所有雷
        clearAllMines() {
                for (let row = 0; row < Minesweeper_GameData.row; row++) {
                        for (let col = 0; col < Minesweeper_GameData.col; col++) {
                                const grid = Minesweeper_GameData.arrGrids[row][col];
                                grid.是否是雷 = false;
                                grid.周围雷数量 = 0;
                                grid.Refresh();
                        }
                }
        }

        //    // 随机放置雷
        placeMinesRandomly() {
                let 雷数 = Minesweeper_GameData.雷数量;
                let 已放雷数 = 0;
                let attempts = 0;
                const maxAttempts = 雷数 * 10; // 防止无限循环

                while (已放雷数 < 雷数 && attempts < maxAttempts) {
                        attempts++;
                        let row = Math.floor(Math.random() * Minesweeper_GameData.row);
                        let col = Math.floor(Math.random() * Minesweeper_GameData.col);

                        let grid = Minesweeper_GameData.arrGrids[row][col];

                        if (!grid.是否是雷) {
                                grid.是否是雷 = true;
                                已放雷数++;
                        }
                }

                if (已放雷数 < 雷数) {
                        console.warn(`警告：只放置了${已放雷数}个雷，目标${雷数}个`);
                }
        }

        //    // 检查是否可解（无猜）
        isSolvableWithoutGuessing(): boolean {
                // 使用更高效的逻辑推理方法
                return this.checkSolvabilityWithLogic();
        }

        //    // 使用逻辑推理检查可解性
        checkSolvabilityWithLogic(): boolean {
                const rows = Minesweeper_GameData.row;
                const cols = Minesweeper_GameData.col;

                // 1. 检查是否有足够的非雷格子连接
                const connectedComponents = this.findConnectedComponents();

                // 2. 检查每个连通分量是否可解
                for (const component of connectedComponents) {
                        if (!this.isComponentSolvable(component)) {
                                return false;
                        }
                }

                return true;
        }

        //    // 找到所有连通分量（非雷格子的连通区域）
        findConnectedComponents(): number[][][] {
                const rows = Minesweeper_GameData.row;
                const cols = Minesweeper_GameData.col;
                const visited = Array(rows).fill(null).map(() => Array(cols).fill(false));
                const components: number[][][] = [];

                for (let row = 0; row < rows; row++) {
                        for (let col = 0; col < cols; col++) {
                                if (!visited[row][col] && !Minesweeper_GameData.arrGrids[row][col].是否是雷) {
                                        const component = new Set<number>();
                                        this.dfsComponent(row, col, visited, component);
                                        components.push(Array.from(component).map(pos => [Math.floor(pos / cols), pos % cols]));
                                }
                        }
                }

                return components;
        }

        //    // 深度优先搜索找连通分量
        dfsComponent(row: number, col: number, visited: boolean[][], component: Set<number>) {
                const rows = Minesweeper_GameData.row;
                const cols = Minesweeper_GameData.col;

                if (row < 0 || row >= rows || col < 0 || col >= cols ||
                        visited[row][col] || Minesweeper_GameData.arrGrids[row][col].是否是雷) {
                        return;
                }

                visited[row][col] = true;
                component.add(row * cols + col);

                // 检查8个方向
                for (let dr = -1; dr <= 1; dr++) {
                        for (let dc = -1; dc <= 1; dc++) {
                                if (dr === 0 && dc === 0) continue;
                                this.dfsComponent(row + dr, col + dc, visited, component);
                        }
                }
        }

        //    // 检查连通分量是否可解
        isComponentSolvable(component: number[][]): boolean {
                if (component.length === 0) return true;

                // 简化检查：如果连通分量中有数字为0的格子，通常可解
                for (const [row, col] of component) {
                        const grid = Minesweeper_GameData.arrGrids[row][col];
                        if (grid.周围雷数量 === 0) {
                                return true; // 有空白区域，通常可解
                        }
                }

                // 更复杂的检查：模拟解决过程
                return this.simulateSolving(component);
        }

        //    // 模拟解决过程
        simulateSolving(component: number[][]): boolean {
                const virtualGrid = this.createVirtualGrid();

                // 从连通分量的每个格子开始尝试
                for (const [startRow, startCol] of component) {
                        if (this.canSolveComponentFromPosition(virtualGrid, component, startRow, startCol)) {
                                return true;
                        }
                }

                return false;
        }

        //    // 检查从指定位置开始是否可以解决整个连通分量
        canSolveComponentFromPosition(virtualGrid: boolean[][], component: number[][], startRow: number, startCol: number): boolean {
                // 复制虚拟网格
                const grid = virtualGrid.map(row => [...row]);

                // 从起始位置开始解决
                this.solveComponentFromPosition(grid, component, startRow, startCol);

                // 检查连通分量中的所有格子是否都被翻开
                for (const [row, col] of component) {
                        if (!grid[row][col]) {
                                return false;
                        }
                }

                return true;
        }

        //    // 从指定位置开始解决连通分量
        solveComponentFromPosition(grid: boolean[][], component: number[][], row: number, col: number) {
                if (row < 0 || row >= Minesweeper_GameData.row ||
                        col < 0 || col >= Minesweeper_GameData.col ||
                        grid[row][col]) {
                        return;
                }

                // 检查是否在连通分量内
                const inComponent = component.some(([r, c]) => r === row && c === col);
                if (!inComponent) {
                        return;
                }

                // 翻开当前格子
                grid[row][col] = true;

                const currentGrid = Minesweeper_GameData.arrGrids[row][col];

                // 如果是雷，停止
                if (currentGrid.是否是雷) {
                        return;
                }

                // 如果周围没有雷，自动展开周围格子
                if (currentGrid.周围雷数量 === 0) {
                        for (let dr = -1; dr <= 1; dr++) {
                                for (let dc = -1; dc <= 1; dc++) {
                                        if (dr === 0 && dc === 0) continue;
                                        this.solveComponentFromPosition(grid, component, row + dr, col + dc);
                                }
                        }
                }
        }

        //    // 创建虚拟网格用于解决检查
        createVirtualGrid(): boolean[][] {
                const virtualGrid = [];
                for (let row = 0; row < Minesweeper_GameData.row; row++) {
                        virtualGrid[row] = [];
                        for (let col = 0; col < Minesweeper_GameData.col; col++) {
                                virtualGrid[row][col] = false; // false表示未翻开
                        }
                }
                return virtualGrid;
        }

        //    // 备用方案：生成简单的可解雷区
        generateFallbackMinesweeper() {
                console.log("使用备用方案生成雷区");

                // 清空所有雷
                this.clearAllMines();

                // 在边缘放置雷，确保中心区域可解
                const 雷数 = Minesweeper_GameData.雷数量;
                let 已放雷数 = 0;

                // 优先在边缘放置雷
                const edgePositions = this.getEdgePositions();

                for (let i = 0; i < Math.min(雷数, edgePositions.length); i++) {
                        const [row, col] = edgePositions[i];
                        const grid = Minesweeper_GameData.arrGrids[row][col];
                        if (!grid.是否是雷) {
                                grid.是否是雷 = true;
                                已放雷数++;
                        }
                }

                // 如果还需要更多雷，随机放置
                while (已放雷数 < 雷数) {
                        let row = Math.floor(Math.random() * Minesweeper_GameData.row);
                        let col = Math.floor(Math.random() * Minesweeper_GameData.col);

                        let grid = Minesweeper_GameData.arrGrids[row][col];
                        if (!grid.是否是雷) {
                                grid.是否是雷 = true;
                                已放雷数++;
                        }
                }

                this.计算每个格子周围雷数量();
                console.log("备用雷区生成完成");
        }

        //    // 获取边缘位置
        getEdgePositions(): [number, number][] {
                const positions: [number, number][] = [];
                const rows = Minesweeper_GameData.row;
                const cols = Minesweeper_GameData.col;

                // 上边缘
                for (let col = 0; col < cols; col++) {
                        positions.push([0, col]);
                }

                // 下边缘
                for (let col = 0; col < cols; col++) {
                        positions.push([rows - 1, col]);
                }

                // 左边缘
                for (let row = 1; row < rows - 1; row++) {
                        positions.push([row, 0]);
                }

                // 右边缘
                for (let row = 1; row < rows - 1; row++) {
                        positions.push([row, cols - 1]);
                }

                // 随机打乱顺序
                for (let i = positions.length - 1; i > 0; i--) {
                        const j = Math.floor(Math.random() * (i + 1));
                        [positions[i], positions[j]] = [positions[j], positions[i]];
                }

                return positions;
        }
        计算每个格子周围雷数量() {
                for (let row = 0; row < Minesweeper_GameData.row; row++) {
                        for (let col = 0; col < Minesweeper_GameData.col; col++) {
                                const grid = Minesweeper_GameData.arrGrids[row][col];

                                if (grid.是否是雷) continue; // 雷格子不用管

                                let count = 0;

                                // 检查周围 8 个方向
                                for (let dr = -1; dr <= 1; dr++) {
                                        for (let dc = -1; dc <= 1; dc++) {
                                                if (dr === 0 && dc === 0) continue; // 跳过自己

                                                let newRow = row + dr;
                                                let newCol = col + dc;

                                                // 判断边界
                                                if (
                                                        newRow >= 0 &&
                                                        newRow < Minesweeper_GameData.row &&
                                                        newCol >= 0 &&
                                                        newCol < Minesweeper_GameData.col
                                                ) {
                                                        if (Minesweeper_GameData.arrGrids[newRow][newCol].是否是雷) {
                                                                count++;
                                                        }
                                                }
                                        }
                                }

                                grid.周围雷数量 = count;
                                grid.Refresh();
                        }
                }
        }
        // async Init_block() {
        // }
        // static Main() {
        // }
        Win() {
                UI.Instance.CreatePanel_sub(`Minesweeper_Prefab`, `UI/Minesweeper_WinPanel`, Minesweeper_WinPanel);
        }
        Lose() {
                UI.Instance.CreatePanel_sub(`Minesweeper_Prefab`, `UI/Minesweeper_LosePanel`, Minesweeper_LosePanel);
        }
        // Replay() {
        //     this.Init();
        // }
        // Reborn() {
        //     this.Init();
        // }
        //    // 处理第一次点击
        handleFirstClick(firstClickRow: number, firstClickCol: number) {
                if (!this._isFirstClick || this._minesPlaced) {
                        return;
                }

                console.log(`第一次点击位置: row=${firstClickRow}, col=${firstClickCol}`);
                this._isFirstClick = false;

                // 生成雷区，确保第一次点击的位置不是雷
                this.generateMinesExcludingPosition(firstClickRow, firstClickCol);

                this._minesPlaced = true;
                console.log("雷区生成完成");
        }

        //    // 生成雷区，排除指定位置
        generateMinesExcludingPosition(excludeRow: number, excludeCol: number) {
                console.log("开始生成无猜扫雷雷区（排除第一次点击位置）...");

                let maxAttempts = 100;
                let attempt = 0;

                while (attempt < maxAttempts) {
                        attempt++;
                        console.log(`第${attempt}次尝试生成雷区`);

                        // 1. 清空所有雷
                        this.clearAllMines();

                        // 2. 随机放置雷（排除第一次点击位置）
                        this.placeMinesRandomlyExcluding(excludeRow, excludeCol);

                        // 3. 计算周围雷数量
                        this.计算每个格子周围雷数量();

                        // 4. 检查是否可解（无猜）
                        if (this.isSolvableWithoutGuessing()) {
                                console.log(`成功生成无猜雷区，尝试${attempt}次`);
                                return;
                        }

                        console.log(`第${attempt}次生成的雷区需要猜测，重新生成`);
                }

                // 如果多次尝试都失败，使用备用方案
                console.log("多次尝试失败，使用备用方案");
                this.generateFallbackMinesweeperExcluding(excludeRow, excludeCol);
        }

        //    // 随机放置雷，排除指定位置
        placeMinesRandomlyExcluding(excludeRow: number, excludeCol: number) {
                let 雷数 = Minesweeper_GameData.雷数量;
                let 已放雷数 = 0;
                let attempts = 0;
                const maxAttempts = 雷数 * 10;

                while (已放雷数 < 雷数 && attempts < maxAttempts) {
                        attempts++;
                        let row = Math.floor(Math.random() * Minesweeper_GameData.row);
                        let col = Math.floor(Math.random() * Minesweeper_GameData.col);

                        // 排除第一次点击的位置
                        if (row === excludeRow && col === excludeCol) {
                                continue;
                        }

                        let grid = Minesweeper_GameData.arrGrids[row][col];

                        if (!grid.是否是雷) {
                                grid.是否是雷 = true;
                                已放雷数++;
                        }
                }

                if (已放雷数 < 雷数) {
                        console.warn(`警告：只放置了${已放雷数}个雷，目标${雷数}个`);
                }
        }

        //    // 备用方案：生成简单的可解雷区，排除指定位置
        generateFallbackMinesweeperExcluding(excludeRow: number, excludeCol: number) {
                console.log("使用备用方案生成雷区（排除第一次点击位置）");

                // 清空所有雷
                this.clearAllMines();

                // 在边缘放置雷，确保中心区域可解
                const 雷数 = Minesweeper_GameData.雷数量;
                let 已放雷数 = 0;

                // 优先在边缘放置雷
                const edgePositions = this.getEdgePositions();

                for (let i = 0; i < Math.min(雷数, edgePositions.length); i++) {
                        const [row, col] = edgePositions[i];
                        // 排除第一次点击的位置
                        if (row === excludeRow && col === excludeCol) {
                                continue;
                        }
                        const grid = Minesweeper_GameData.arrGrids[row][col];
                        if (!grid.是否是雷) {
                                grid.是否是雷 = true;
                                已放雷数++;
                        }
                }

                // 如果还需要更多雷，随机放置
                while (已放雷数 < 雷数) {
                        let row = Math.floor(Math.random() * Minesweeper_GameData.row);
                        let col = Math.floor(Math.random() * Minesweeper_GameData.col);

                        // 排除第一次点击的位置
                        if (row === excludeRow && col === excludeCol) {
                                continue;
                        }

                        let grid = Minesweeper_GameData.arrGrids[row][col];
                        if (!grid.是否是雷) {
                                grid.是否是雷 = true;
                                已放雷数++;
                        }
                }

                this.计算每个格子周围雷数量();
                console.log("备用雷区生成完成");
        }
        //    // 测试无猜扫雷功能
        testNoGuessMinesweeper() {
                console.log("开始测试无猜扫雷功能...");

                // 重置游戏
                this.resetGame();

                // 等待网格初始化完成
                setTimeout(() => {
                        console.log("网格初始化完成，开始测试...");

                        // 模拟第一次点击
                        const testRow = Math.floor(Minesweeper_GameData.row / 2);
                        const testCol = Math.floor(Minesweeper_GameData.col / 2);

                        console.log(`测试点击位置: row=${testRow}, col=${testCol}`);

                        // 检查点击位置是否不是雷
                        const grid = Minesweeper_GameData.arrGrids[testRow][testCol];
                        if (grid && !grid.是否是雷) {
                                console.log("✅ 第一次点击位置不是雷，测试通过");

                                // 检查是否可解
                                if (this.isSolvableWithoutGuessing()) {
                                        console.log("✅ 生成的雷区可解，无猜功能正常");
                                } else {
                                        console.log("❌ 生成的雷区不可解，需要检查算法");
                                }
                        } else {
                                console.log("❌ 第一次点击位置是雷，测试失败");
                        }
                }, 1000);
        }
}

// /** 调试 */
window["Minesweeper_GameManager"] = Minesweeper_GameManager;